package com.shuai.user.client;


import com.shuai.common.constant.InterfaceConstant;
import com.shuai.user.domain.dto.ItrRankVO;
import com.shuai.user.domain.dto.ItrRedisDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 操作Redis中接口的平均响应时间排行榜的redis客户端
 */
@Component
public class RedisForItrClient {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    public void updateItrRank(ItrRedisDTO itrRedisDTO) {
        // 更新接口响应时间
        String invokeTime = stringRedisTemplate.opsForValue().get(InterfaceConstant.API_RPS_TIME_REDIS_KEY + itrRedisDTO.getInterfaceId());
        if (invokeTime == null || StringUtils.isBlank(invokeTime)) {
            stringRedisTemplate.opsForValue().set(InterfaceConstant.API_RPS_TIME_REDIS_KEY + itrRedisDTO.getInterfaceId(), itrRedisDTO.getRpsTime().toString());
        } else {
            stringRedisTemplate.opsForValue().increment(InterfaceConstant.API_RPS_TIME_REDIS_KEY + itrRedisDTO.getInterfaceId(), itrRedisDTO.getRpsTime());
        }

        // 更新接口调用次数
        Double score = redisTemplate.opsForZSet().score(InterfaceConstant.API_INVOKE_COUNT_RANK_REDIS_KEY, itrRedisDTO.getInterfaceId());
        if (score == null) {
            redisTemplate.opsForZSet().add(InterfaceConstant.API_INVOKE_COUNT_RANK_REDIS_KEY, itrRedisDTO.getInterfaceId(), 1.0);
        } else {
            redisTemplate.opsForZSet().incrementScore(InterfaceConstant.API_INVOKE_COUNT_RANK_REDIS_KEY, itrRedisDTO.getInterfaceId(), 1.0);
        }
    }


    /**
     * 返回排行榜
     */
    public List<ItrRankVO> getRank(long topN) {
        Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet().rangeWithScores(InterfaceConstant.API_INVOKE_COUNT_RANK_REDIS_KEY, 0, topN - 1);
        if (typedTuples == null || typedTuples.isEmpty()) {
            return new ArrayList<>();
        }
        return typedTuples.stream().map((item) -> {
            ItrRankVO itrRankVO = new ItrRankVO();
            Double invokeCountTotal = item.getScore();
            String rpsTimeTotal = stringRedisTemplate.opsForValue().get(InterfaceConstant.API_RPS_TIME_REDIS_KEY + item.getValue());
            if (invokeCountTotal == null || rpsTimeTotal == null) {
                return itrRankVO;
            }
            itrRankVO.setInterfaceId(Long.parseLong(item.getValue().toString()));
            itrRankVO.setInvokeCount(invokeCountTotal.longValue());
            itrRankVO.setAvgRpsTime(Double.parseDouble(rpsTimeTotal) / invokeCountTotal);
            return itrRankVO;
        }).collect(Collectors.toList());
    }
}
